/*
 "kid-e-log" - The time clock for obsessive parenting
 tronixstuff.com - CC by-sa-nc 
 December 2010
 */

// prepare for LCD module
#include <LiquidCrystal.h> 
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); 


// prepare for I2C bus and connected devices
#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68
#define chip1 0x50


// store value for three RFID tags
int yellowtag[14] = {
  2,51,67,48,48,67,69,49,48,68,53,51,55,3}; // yellow tag
int redtag[14] = {
  2,51,67,48,48,67,67,51,69,69,51,50,68,3}; // red tag
int bluetag[14] = {
  2,51,68,48,48,52,53,67,57,66,69,48,70,3}; // blue tag
int newtag[14] = {
  0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // used for read comparisons
int parentcard[14] = {
  2,51,69,48,48,49,65,57,56,57,70,50,51,3}; // parent's card - resets eeprom when read

void setup() 
{
  lcd.begin(16, 2);             // need to specify how many columns and rows are in the LCD unit
  lcd.setCursor(0,0);
  lcd.print("kid-e-log * v0.9");
  lcd.setCursor(0,1);
  lcd.print(" tronixstuff.com");
  delay(3000);
  Serial.begin(9600); // enable serial port to receive data from RFID reader
  Wire.begin();                 // start the I2C bus
  Serial.flush();               // need to flush serial buffer, otherwise first tag read from reset/power on may not be correct
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // used for setting time on DS1307
  second = 0;
  minute = 23;
  hour = 23;
  dayOfWeek = 4;
  dayOfMonth = 19;
  month = 5;
  year = 10;
  // setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}

// Convert normal decimal numbers to binary coded decimal for DS1307
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers for DS1307
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// sets the date/time to the DS1307. Only call when necessary, then reupload sketch with function commented out
void setDateDs1307(byte second,        // 0-59
byte minute,        // 0-59
byte hour,          // 1-23
byte dayOfWeek,     // 1-7
byte dayOfMonth,    // 1-28/29/30/31
byte month,         // 1-12
byte year)          // 0-99
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
  Wire.send(decToBcd(minute));
  Wire.send(decToBcd(hour));     
  Wire.send(decToBcd(dayOfWeek));
  Wire.send(decToBcd(dayOfMonth));
  Wire.send(decToBcd(month));
  Wire.send(decToBcd(year));
  Wire.send(0x10); // sends 0x10 (hex) 00010000 (binary) to control register - turns on square wave
  Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

byte readData(int device, unsigned int add) // reads a byte of data from memory location 'add' in chip at I2C address 'device'
{
  byte result;  // returned value
  Wire.beginTransmission(device); //  these three lines set the pointer position in the EEPROM
  Wire.send((int)(add >> 8));   // left-part of pointer address
  Wire.send((int)(add & 0xFF)); // and the right
  Wire.endTransmission();
  Wire.requestFrom(device,1); // now get the byte of data...
  result = Wire.receive();  
  return result; // and return it as a result of the function readData
}

void writeData(int device, unsigned int add, byte data)
// writes a byte of data 'data' to the eeprom at I2C address 'device', in memory location 'add'
{
  Wire.beginTransmission(device);
  Wire.send((int)(add >> 8));   // left-part of pointer address
  Wire.send((int)(add & 0xFF)); // and the right
  Wire.send(data);
  Wire.endTransmission();
  delay(10);
}


void displayData()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // get the time data from the DS1307
  byte d=0; // variable to handle data coming out of eeprom
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  // display time and date on top line of LCD
  lcd.clear(); // clear LCD screen
  lcd.setCursor(1,0);
  lcd.print(dayOfMonth, DEC);
  lcd.print("/");
  lcd.print(month, DEC);
  lcd.print("/");
  lcd.print(year, DEC);
  lcd.print(" ");
  if (hour<10)
  {
    lcd.print("0");
  }
  lcd.print(hour, DEC);
  if (minute<10)
  {
    lcd.print("0");
  }
  lcd.print(minute, DEC);
  lcd.print("h");

  // now display tag data on bottom line of LCD
  lcd.setCursor(1,1);

  d=readData(chip1,0);
  if (d==0) // is tag 1 home?
  { // no
    lcd.print("---- ");
  } 
  else if (d==1)
  { // yes
    d=readData(chip1,1); // tag 1, hour
    if (d<10)
    {
      lcd.print("0");
    }
    lcd.print(d, DEC);
    d=readData(chip1,2); // tag 1, minutes
    if (d<10)
    {
      lcd.print("0");
    }
    lcd.print(d, DEC);
    lcd.print(" ");
  }

  d=readData(chip1,3);
  if (d==0) // is tag 2 home?
  { // no
    lcd.print("---- ");
  } 
  else if (d==1)
  { // yes
    d=readData(chip1,4); // tag 2, hour
    if (d<10)
    {
      lcd.print("0");
    }

    lcd.print(d, DEC);
    d=readData(chip1,5); // tag 2, minutes
    if (d<10)
    {
      lcd.print("0");
    }

    lcd.print(d, DEC);
    lcd.print(" ");
  }

  d=readData(chip1,6);
  if (d==0) // is tag 3 home?
  { // no
    lcd.print("---- ");
  } 
  else if (d==1)
  { // yes
    d=readData(chip1,7); // tag 3, hour
    lcd.print(d, DEC);
    d=readData(chip1,8); // tag 3, minutes
    if (d<10)
    {
      lcd.print("0");
    }

    lcd.print(d, DEC);
  }
}

void fourAM()
// checks if time is 4AM, and if so - resets the check-in times for the three children/tags
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // get the time data from the DS1307
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // overkill but saves time
  if ((hour==4)&&(minute==0))
  {
    // wipe eeprom data (sets registers to 0)
    for (int a=0; a<9; a++)
    {
      writeData(chip1,a,0);
    }
    // wait until 0400h has elapsed - to save unnecessary writes to the eeprom
    delay(62000);
  }
}

boolean comparetag(int aa[14], int bb[14])
//  compares two arrrays, returns true if identical - good for comparing tags
{
  boolean ff=false;
  int fg=0;
  for (int cc=0; cc<14; cc++)
  {
    if (aa[cc]==bb[cc])
    {
      fg++;
    }
  }
  if (fg==14)
  {
    ff=true;
  }
  return ff;
}

void readTags()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; // get the time data from the DS1307
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year); // overkill but saves time
  int data1=0;
  if (Serial.available() > 0) // if a read has been attempted
  {
    // read the incoming number on serial RX
    delay(100);  // Needed to allow time for the data to come in from the serial buffer. 
    for (int z=0; z<14; z++) // read the rest of the tag
    {
      data1=Serial.read();
      newtag[z]=data1;
    }
    Serial.flush(); // stops multiple reads
    // now to match tags up
    if (comparetag(newtag,yellowtag)==true)
    {
      // write time for yellow tag in eeprom position 0~2
      writeData(chip1,0,1);
      writeData(chip1,1,hour);
      writeData(chip1,2,minute);
    }
    if (comparetag(newtag,redtag)==true)
    {
      // write time for yellow tag in eeprom position 0~2
      writeData(chip1,3,1);
      writeData(chip1,4,hour);
      writeData(chip1,5,minute);
    }
    if (comparetag(newtag,bluetag)==true)
    {
      // write time for yellow tag in eeprom position 0~2
      writeData(chip1,6,1);
      writeData(chip1,7,hour);
      writeData(chip1,8,minute);
    }
    if (comparetag(newtag,parentcard)==true)
    {
      wipe();
    }
  }
}

void wipe()
// resets eeprom data 
{
  for (int a=0; a<9; a++)
  {
    writeData(chip1,a,0);
  }
}

void loop()
{
  readTags();
  displayData(); // shows the time and tag status data on the LCD
  delay(350); // slows refresh rate of LCD to stop flickering
  fourAM(); //  checks if it is 4am and time to reset the eepsom data
}




